avatar

目录
331 - cpp内置命名空间

331 - C++内置命名空间

🧑‍💻 User

In this lecture, I want to raise your awareness on builtin namespaces, which is something we havebeen using all along without really knowing that they are namespaces.And we’re going to look at a few examples.Right now.Let’s head over to Visual Studio code and do that.Okay.So here we are in our working directory.The current project is built in namespaces.We’re going to set up a project very fast.We’re going to grab our template files, we’re going to put those in place, and we’re going to openthis little guy in Visual Studio code.We’re going to have our main CPP file opened up and we want to see that We have been using namespacesall along without really knowing it.And the first instance where we use namespaces, I think it was when we printed things out on the consoleusing Stdcout, let’s do that.We’re going to say hello world.Okay, so we’re going to say Stdendl and STD is actually a built in namespace that contains many thingsin the C plus plus standard library.If you take out the C out here, you’re going to see that the C plus plus compiler is not going to knowwhat you are talking about.If you try to compile this program, you’re going to get a compiler error and it’s going to say C outwas not declared in this scope.It’s going to say Endl was not declared in this scope because the C plus compiler doesn’t know wherethese things are declared, but we know that they live in the STD namespace.So we’re going to prefix this with STD, colon colon and please notice that this is the same syntaxwe use to access things in our own Customly defined namespaces in a few lectures that we have done before.So we’re going to go here and say Stdendl and now the C plus plus compiler is going to take this becauseSTD is a built in namespace that happens to contain a lot of things in the C plus plus standard library.Let’s world.You’re going to see that this is going to work.The world is good.If we run this, we’re going to see Hello world.Let’s set up a terminal and run Rooster.You’re going to see Hello World printed out here.And this is really cool.Another thing that we have seen that lives in the STD namespace I think is String.The string class we use to manipulate things in our code.For example, we can say STD string and say message and we can put in whatever message we want.So we’re going to say Hello world and we can print out this message.Okay, so we can do something like this.But the message here is that the string class is living in the STD namespace.Many of the things we have called were living in the STD namespace and now you know that the STD thingwe have here is a built in namespace from the C plus plus standard library.This is really what I wanted you to see.If you want, you can head over to your favorite search engine and say C plus plus standard libraryand let’s see what we can get just to to look around.We’re going to see a search result from CPP reference.You can even look at the C plus plus standard library link here for Wikipedia.You’re going to see the information here and you can really read these things.But what I want you to see is that the C plus plus standard library contains many things.You can see that we have concepts inside.We have coroutines.We’re going to learn about this later in the course.So for now, just ignore this.But if you go down, you’re going to see that we have many things that we even had a chance to use inthe course.I think we had a chance to use a few things from C stdlib when we were doing random numbers.Let’s go down and see if we have something we have used.We have used this facilities to transform back and forth between strings and numbers.If you go to a to I, for example, here, this is going to open up and you’re going to see that thesethings also live in the standard namespace STD like you see here.So many things from the C plus plus standard library are defined in the STD namespace and you need tobe aware of this.This is really all I wanted you to see in this lecture.I hope you found it interesting.We are going to stop here in this one and the next one we’re going to learn about using declarations.Go ahead and finish up here and meet me there.


🤖 Assistant

好的!作为您的 C++ 导师,我很高兴能引导您学习 C++ 中一个非常基础但极其重要的概念:内置命名空间 [builtin namespaces]。


C++ 内置命名空间:揭秘 std 的奥秘

摘要: 本节课将深入探讨 C++ 中我们一直在使用却可能没有意识到的内置命名空间,特别是 std 命名空间。我们将学习它如何组织标准库中的各种功能,以及为什么在使用 std::coutstd::string 等时需要 std:: 前缀。


1. 什么是命名空间 (Namespace)?

在深入了解内置命名空间之前,让我们快速回顾一下命名空间的概念。

想象一下您在一个非常大的图书馆里,里面有成千上万的书。如果所有书都直接放在地上,没有分类,那么找到一本特定的书会非常困难,甚至可能出现不同作者写了同名书的情况,导致混淆。

命名空间 [namespace] 在 C++ 中扮演的角色就像是图书馆的“分类区”或者“书架标签”。它的主要目的是:

  • 避免命名冲突 (Name Collisions): 当您和他人编写的代码中,如果定义了相同名字的函数或变量,如果没有命名空间,就会发生冲突。命名空间将这些名字“包裹”起来,使得不同命名空间中的同名实体可以共存。
  • 组织代码 (Organize Code): 将相关的函数、类、变量等组织在一个逻辑单元内,提高代码的可读性和管理性。

我们在之前的课程中可能已经学习过如何定义自己的自定义命名空间 [customly defined namespaces]。例如:

cpp
1
2
3
4
5
6
7
8
9
10
11
12
// 假设我们之前定义过这样的命名空间
namespace MyUtilities {
int add(int a, int b) {
return a + b;
}
}

namespace AnotherModule {
int add(int a, int b) { // 即使函数名相同,也不会冲突,因为它们在不同命名空间
return a * b;
}
}

要使用 MyUtilities 命名空间中的 add 函数,我们需要写 MyUtilities::add(1, 2)。这里的 :: 就是“作用域解析运算符” [scope resolution operator],它告诉编译器:“去 MyUtilities 这个命名空间里找 add。”

2. 揭秘 std 命名空间:你一直都在用它!

现在,我们来聊聊 C++ 中最常用也最特殊的内置命名空间——std

std 是 “standard”(标准)的缩写。它是一个 C++ 语言提供的特殊命名空间,包含了 C++ 标准库 [C++ Standard Library] 的绝大部分内容。C++ 标准库是一个巨大的工具箱,里面有各种各样的预定义功能,比如输入输出、字符串操作、容器(如列表、映射)、算法等等。

您可能在不知不觉中已经一直在使用 std 命名空间中的功能了!最常见的例子就是我们用来在控制台 [console] 上打印输出的 std::cout

2.1 std::coutstd::endl

让我们来看这个经典的 “Hello World” 程序:

cpp
1
2
3
4
5
6
#include <iostream> // 引入输入输出流库

int main() {
std::cout << "Hello World!" << std::endl; // 使用 std::cout 和 std::endl
return 0;
}

在这里:

  • cout 是一个负责将数据输出到控制台的对象。
  • endl 是一个操纵符 [manipulator],它会插入一个换行符 [newline character] 并刷新 [flush] 输出缓冲区 [output buffer],确保内容立即显示。

那么,为什么我们要写 std::coutstd::endl 呢?

因为 coutendl 都是在 std 命名空间中定义的! C++ 编译器 [compiler] 需要知道它们在哪里被声明。如果不加 std:: 前缀,编译器就会一脸茫然,因为它不知道 coutendl 是什么东西,在哪里能找到它们。

错误示范(请勿模仿):

cpp
1
2
3
4
5
6
7
#include <iostream>

int main() {
// 假设我们这样写,编译器会报错!
cout << "Hello World!" << endl;
return 0;
}

如果您尝试编译上面的代码,您会收到类似于这样的编译错误 [compiler error]:
'cout' was not declared in this scope (cout 未在此作用域中声明)
'endl' was not declared in this scope (endl 未在此作用域中声明)

这意味着在当前你写代码的这个“区域”(也就是 main 函数所在的全局或局部作用域 [scope]),编译器找不到 coutendl 的定义。它不知道这些名字指的是什么。

所以,通过前缀 std::,我们明确告诉编译器:“去 std 这个命名空间里面找 coutendl!” 这样,编译器就能顺利找到并使用它们了。

2.2 std::string

除了 coutendlstd 命名空间还包含许多其他非常有用的功能。其中一个就是 string 类,用于处理文本字符串 [text strings]。

cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream> // 用于 cout
#include <string> // 用于 string 类

int main() {
std::string message = "C++ 编程真有趣!"; // 声明一个 std::string 类型的变量
std::cout << message << std::endl;

// 你还可以对 std::string 进行各种操作,比如拼接
std::string greeting = "你好,";
std::string full_message = greeting + message;
std::cout << full_message << std::endl;

return 0;
}

在这里,string 类也是在 std 命名空间中定义的,因此我们也需要使用 std::string 来声明一个字符串变量。

2.3 其他 std 命名空间中的例子

C++ 标准库非常庞大,std 命名空间中包含了海量的功能,例如:

  • 容器 (Containers): std::vector (动态数组)、std::map (键值对映射) 等。
  • 算法 (Algorithms): std::sort (排序)、std::find (查找) 等。
  • 数值转换 (Numeric Conversions): 比如将字符串转换为整数的 std::stoi (string to integer) 或 std::atoi (ASCII to integer)。
    • std::stoi 是 C++11 及更高版本推荐的,它更安全,因为它会抛出异常处理无效输入。
    • std::atoi 通常来自 C 语言库,在 C++ 中通常通过 std:: 访问,但它不会报告错误。
    • 例如使用 std::stoi
      cpp
      1
      2
      3
      4
      5
      6
      7
      8
      9
      #include <iostream>
      #include <string> // For std::string and std::stoi

      int main() {
      std::string num_str = "12345";
      int number = std::stoi(num_str); // 将字符串 "12345" 转换为整数 12345
      std::cout << "转换后的数字是: " << number << std::endl;
      return 0;
      }

总而言之,当你看到一个像 std:: 这样的前缀时,你应该立刻意识到它是在指一个在 std 命名空间中定义的实体。这是一种告诉编译器去哪里找到你需要的功能的标准方式。

3. 为什么 C++ 标准库要用命名空间?

原因与我们之前讨论的自定义命名空间一样:组织和避免冲突

设想一下,如果 C++ 标准库中的所有函数、类、变量都直接放在全局作用域 [global scope] 中,没有任何命名空间包裹。那么,您自己定义的任何 coutstringvector 等名字,都将与标准库中的名字发生冲突,导致您的程序无法编译。std 命名空间有效地“隔离”了标准库的名字,确保了您的代码可以自由地使用自己的名字,而不会与标准库发生冲突。

4. QA 闪卡 (Flash Cards)

这里有一些关于本节内容的快速问答,帮助您巩固知识:

Q1: std 在 C++ 中代表什么?
A1: std 是 “standard” 的缩写,它是 C++ 标准库大部分内容所处的内置命名空间。

Q2: 为什么在使用 coutstring 等时,通常需要在前面加上 std::
A2: 因为 coutstring 等功能都是在 std 命名空间中定义的。 std:: 告诉编译器去 std 命名空间中查找这些名字,否则编译器会报错说它们“未声明”。

Q3: ::std::cout 中表示什么意思?
A3: :: 是 C++ 中的“作用域解析运算符” [scope resolution operator],它用于指定一个名字所属的命名空间或类。

Q4: 如果不使用 std:: 前缀,会发生什么?
A4: 编译器会产生错误,提示相关名称(如 coutendl)“未在此作用域中声明”。

Q5: 除了 coutstring,你还知道哪些常用功能在 std 命名空间中?
A5: std::endl, std::vector, std::map, std::sort, std::stoi 等。

5. 常见的误解或错误 (Common Misunderstandings or Mistakes)

作为 C++ 新手,在使用 std 命名空间时,可能会犯一些常见的错误或产生误解:

  1. 忘记 std:: 前缀: 这是最常见的问题。新手经常会忘记为标准库的元素加上 std:: 前缀,导致编译错误。记住,除了少数例外(例如 C 风格的头文件),几乎所有标准库的功能都需要 std::
  2. 混淆 ::. (点运算符): :: 是作用域解析运算符,用于访问命名空间或类中的静态成员。. 是成员访问运算符,用于访问对象的成员(例如 myObject.member)。它们用途不同,不能混淆。
  3. 认为 std 是一个数据类型或关键字: std 不是数据类型,也不是一个像 intclass 那样的关键字 [keyword]。它是一个命名空间的名称。
  4. 过度依赖 using namespace std;: 虽然在某些教程中可能会看到 using namespace std; 这样的语句(我们下一节课会详细讲到它),但作为新手,在项目早期阶段最好避免在头文件或全局作用域中大量使用它。因为它会将 std 命名空间中的所有名字都引入当前作用域,增加了命名冲突的风险,尤其是在大型项目中。在本节课中,我们强调手动使用 std:: 是为了让你清晰地认识到这些功能来自标准库。

6. 编程练习 (Coding Exercise)

为了帮助您更好地理解和掌握 std 命名空间的使用,请完成下面的代码练习。

任务: 下面的 C++ 代码片段尝试进行一些基本的输入输出和字符串操作。请您修改代码中缺失 std:: 前缀的部分,使其能够正确编译并运行。

cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>

int main() {
// 1. 打印一条欢迎信息
cout << "欢迎来到 C++ 编程世界!" << endl;

// 2. 声明一个字符串变量并赋值
string userName = "张三";

// 3. 打印出用户的名字
cout << "你好," << userName << endl;

// 4. 将一个字符串转换为整数并打印
string ageStr = "30";
int age = stoi(ageStr);
cout << "你的年龄是: " << age << endl;

return 0;
}

请您将修改后的代码粘贴在回复中。


评论